﻿using Core.Dtos;
using Core.Entities;
using Core.IRepository;
using Core.Messages;
using Core.Queries;
using Library.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Microsoft.AspNet.Identity;
using System.Web;
using Core.ViewModels;
using System.Threading.Tasks;

namespace Front.Controllers.Api
{
    public class ItemApiController : CrudBaseController<int, ItemValue, ItemValueDto, ItemValueQuery>
    {
        IItemRepository ItemRepository;
        public ItemApiController(IUnitOfWork UnitOfWork, IItemValueRepository ItemValueRepository, IItemRepository ItemRepository)
            : base(UnitOfWork, ItemValueRepository)
        {
            this.ItemRepository = ItemRepository;
        }

        [HttpPost]
        [Route("api/itemapi/findbyid/{id}")]
        public ItemDto FindById(int id)
        {
            Item entity = ItemRepository.FindBy(id);
            ItemDto dto = AutoMapper.Mapper.Map<Item, ItemDto>(entity);
            return dto;
        }
     
        [HttpPost]
        [Route("api/itemapi/sfindby")]
        public ListResponse<ItemDto> SimpleFindBy(BaseRequest<ItemQuery> request)
        {
            return SimpleFindBy<ItemDto>(request);
        }

        private ListResponse<T> SimpleFindBy<T>(BaseRequest<ItemQuery> request)
        {
            ItemQuery query = request.Value;
            ListResponse<T> response = new ListResponse<T>();
            try
            {
                ListResponse<Item> dbResponse = ItemRepository.FindBy(query);

                response.List = AutoMapperHelper.MapList<Item, T>(dbResponse.List).ToList();
                response.RowsCount = dbResponse.RowsCount;
                response.PageNumber = query.PageNumber;
                response.PageSize = query.PageSize;
                response.Success = true;
            }
            catch (Exception ex)
            {
                response.Success = false;
                response.ErrorMessage = ex.ToString();
            }

            return response;
        }

        [HttpPost]
        [Route("api/itemapi/tfindby")]
        public ListResponse<ItemValueDto> TabularFindBy(BaseRequest<DynamicItemQuery> request)
        {
            //articleid not null
            //check if it has rights to see that items
            ListResponse<ItemValueDto> result = null;
            ItemValueQuery query;
            
            List<ColumnFilter> filters = new List<ColumnFilter>();
            if (request.Value.Filters != null)
            {
                for (int i = 0; i < request.Value.Filters.Count; i++)
                {
                    if (!string.IsNullOrWhiteSpace(request.Value.Filters[i].Value))
                    {
                        filters.Add(request.Value.Filters[i]);
                    }
                }
            }

            if(filters.Count > 0)
            {
                List<int[]> itemsIDsList = new List<int[]>();
                int[] itemIDs;
                ListResponse<ItemValueDto> filterResult;

                query = new ItemValueQuery() { ArticleID = request.Value.ArticleID };                

                Parallel.For(0, filters.Count, i =>
                {
                    query.ColumnID = filters[i].ID;
                    query.Value = filters[i].Value;

                    filterResult = base.DefaultFindBy(query);
                    int[] tempItemIDs = filterResult.List.Select(x => x.ItemID).ToArray();
                    itemsIDsList.Add(tempItemIDs);  
                });

                itemIDs = itemsIDsList[0];
                for (int i = 1; i < itemsIDsList.Count; i++)
                {
                    itemIDs = itemIDs.Intersect(itemsIDsList[i]).ToArray();
                }

                if (itemIDs.Length > 0) 
                {
                    query = BuildQueryWithPagination(request);
                    query.ItemIDs = itemIDs;
                    result = base.DefaultFindBy(query);
                }
                else
                {
                    //no result
                    result = new ListResponse<ItemValueDto>();
                    result.RowsCount = 0;
                    result.PageNumber = request.Value.PageNumber;
                    result.PageSize = request.Value.PageSize;
                }
            }
            else
            {
                //search with no filters
                query = BuildQueryWithPagination(request);
                result = base.DefaultFindBy(query);                
            }

            if (request.Value.ComputePagesCount && request.Value.ColumnsCount > 0)
                result.RowsCount = result.RowsCount / request.Value.ColumnsCount;
                                   
            return result;
        }

        private ItemValueQuery BuildQueryWithPagination(BaseRequest<DynamicItemQuery> request)
        {
            int pageSize = request.Value.PageSize * request.Value.ColumnsCount;
            return new ItemValueQuery() { ArticleID = request.Value.ArticleID, PageSize = pageSize, SortColumn = request.Value.SortColumn, PageNumber = request.Value.PageNumber };
        }

        public BaseResponse<int> Post(BaseRequest<ItemDto> request)
        {
            BaseResponse<int> response = new BaseResponse<int>();

            Item item = request.Value.ToEntity();
            item.DateCreated = DateTime.Now;            
            ItemRepository.Add(item);
            UnitOfWork.Commit();
            
            if(request.Value.DataItems != null)
            for (int i = 0; i < request.Value.DataItems.Count; i++)
            {
                request.Value.DataItems[i].ItemID = item.ID;
                base.DefaultAdd(request.Value.DataItems[i]);
            }
            response.Value = item.ID;
            response.Success = true;
            return response; 
        }

        public BaseResponse Put(int id, BaseRequest<ItemDto> request)
        {
            BaseResponse response = new BaseResponse();            
            Item item = ItemRepository.FindBy(request.Value.ID);            
            AutoMapper.Mapper.Map<ItemDto, Item>(request.Value, item);
            item.DateLastModified = DateTime.Now;
            ItemRepository.Edit(item);

            if (request.Value.DataItems != null)
            for (int i = 0; i < request.Value.DataItems.Count; i++)
            {
                if (request.Value.DataItems[i].ItemID == 0)
                {
                    request.Value.DataItems[i].ItemID = request.Value.ID;
                    base.DefaultAdd(request.Value.DataItems[i]);
                }
                else
                    base.DefaultEdit(request.Value.DataItems[i].ID, request.Value.DataItems[i]);
            }

            UnitOfWork.Commit();
            response.Success = true;
            return response;            
        }

        public override BaseResponse Delete(int id)
        {
            BaseResponse response = new BaseResponse();
            try
            {
                Repository.Delete(x => x.ItemID == id);
                ItemRepository.Delete(x => x.ID == id);                
                UnitOfWork.Commit();
                response.Success = true;
            }
            catch (Exception ex)
            {
                response.Success = false;
                response.ErrorMessage = ex.ToString();
            }

            return response;
        }

        [HttpPost]
        [Route("api/itemapi/export")]
        public HttpResponseMessage Export(ItemQuery query)
        {
            BaseRequest<ItemQuery> request = new BaseRequest<ItemQuery>();
            request.Value = query;
            request.Value.PageSize = 0;

            ListResponse<SimpleListExportItemVM> list = SimpleFindBy<SimpleListExportItemVM>(request);
            return ExcelExportHelper.GenerateExcelResponseMessage<SimpleListExportItemVM>(list.List.ToList());                        
        }        
    }
}
